'abuvelocitycomponent.monkey by Belimoth

'TODO
'	implement UNIT_ constants

Strict
Import abutime
Import abucomponent



Interface IVelocity
	Method XVelocity:Float() Property
	Method XVelocity:Void(xVelocityNew:Float) Property
	Method YVelocity:Float() Property
	Method YVelocity:Void(yVelocityNew:Float) Property
	
	Method XAcceleration:Float() Property
	Method XAcceleration:Void(xAccelerationNew:Float) Property
	Method YAcceleration:Float() Property
	Method YAcceleration:Void(yAccelerationNew:Float) Property
	
	Method XMaxVelocity:Float() Property
	Method YMaxVelocity:Float() Property
	Method SetMaxVelocity:Void(x:Float, y:Float)
	
	Method XDisplacement:Int() Property
	Method YDisplacement:Int() Property
End



Class VelocityComponent Extends EntityComponent Implements IVelocity, IJuggleable

Public
	Global juggler := New Juggler<VelocityComponent>
	Global unit:Int = UNIT_FRAMES				'not implemented yet
	
	Method Initialize:Void(owner:IEntity)
		Super.Initialize(owner)
		juggler.Add(Self)
	End
	
	Method Finalize:Void()
		juggler.Remove(Self)
	End
	
	'Implements IJuggleable
	Method Active:Bool() Property Return True End												'Return Not(owner._markedForDeletion)
	
	Method Juggle:Void(timePassed:Int = 0)		'frames only for now
		_xVelocity += _xAcceleration
		_yVelocity += _yAcceleration
		_xVelocity = Max( -_xMaxVelocity, Min(_xMaxVelocity, _xVelocity) )				'untested
		_yVelocity = Max( -_yMaxVelocity, Min(_yMaxVelocity, _yVelocity) )				'untested
	End
	
	'Implements IVelocity
	Method XVelocity:Float() Property															Return _xVelocity														End
	Method XVelocity:Void(xVelocityNew:Float) Property
		_xVelocity = xVelocityNew
		If _xVelocity = 0 Then _xRemainder = 0
	End
	Method YVelocity:Float() Property															Return _yVelocity														End
	Method YVelocity:Void(yVelocityNew:Float) Property
		_yVelocity = yVelocityNew
		If _yVelocity = 0 Then _yRemainder = 0
	End
	
	Method XAcceleration:Float() Property														Return _xAcceleration													End
	Method XAcceleration:Void(xAccelerationNew:Float) Property									_xAcceleration = xAccelerationNew										End
	Method YAcceleration:Float() Property														Return _yAcceleration													End
	Method YAcceleration:Void(yAccelerationNew:Float) Property									_yAcceleration = yAccelerationNew										End
	
	Method XMaxVelocity:Float() Property														Return _xMaxVelocity													End
	Method YMaxVelocity:Float() Property														Return _yMaxVelocity													End
	
	Method XDisplacement:Int() Property
		Local dx:Int = Int(_xVelocity + _xRemainder)
		_xRemainder = _xVelocity - dx
		Return dx
	End
	Method YDisplacement:Int() Property
		Local dy:Int = Int(_yVelocity + _yRemainder)
		_yRemainder = _yVelocity - dy
		Return dy
	End
	
	Method SetMaxVelocity:Void(x:Float, y:Float)
		_xMaxVelocity = x
		_yMaxVelocity = y
	End
	
Private
	Field _xVelocity:Float, _yVelocity:Float
	Field _xAcceleration:Float, _yAcceleration:Float
	Field _xMaxVelocity:Float = 2147483647
	Field _yMaxVelocity:Float = 2147483647
	Field _xRemainder:Float, _yRemainder:Float
End



Const V_2:Int  = %0000010
Const V_4:Int  = %0000100
Const V_8:Int  = %0001000
Const V_16:Int = %0010000
Const V_32:Int = %0100000
Const V_64:Int = %1000000


#Rem
Class MyVelocityComponent' Extends EntityComponent 'Implements IVelocity, IJuggleable			'TODO replace above with this

Public
	Method xVelocity:Float() Property Return xvNominal End
	Method xVelocity:Void(xVelocityNew:Float) Property
		'TODO
	End
	
	Method yVelocity:Float() Property Return yvNominal End
	Method yVelocity:Void(yVelocityNew:Float) Property
		'TODO
	End

Private
	Field xvNominal:Float
	Field yvNominal:Float
	Field xvActual:Int
	Field yvActual:Int
	Field xvFractional:Int
	Field yvFractional:Int
	
	Field xRemainder:Float
	Field yRemainder:Float
End
#End


Function UpdateVelocities:Void(timePassed:Int = -1)
	If timePassed = -1 Then timePassed = Tick()
	VelocityComponent.juggler.Update(timePassed)
End